package com.hope.hotel.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hope.hotel.common.Result;
import com.hope.hotel.entity.DAO.HotelNewDAO;
import com.hope.hotel.entity.dto.AmenitiesDTO;
import com.hope.hotel.entity.dto.LocationDTO;
import com.hope.hotel.entity.dto.PolicyDTO;
import com.hope.hotel.entity.po.Amenities;
import com.hope.hotel.entity.po.Hotel;
import com.hope.hotel.entity.po.Location;
import com.hope.hotel.entity.po.Policy;
import com.hope.hotel.entity.po.Rooms;
import com.hope.hotel.entity.vo.HotelVO;
import com.hope.hotel.mapper.AmenitiesMapper;
import com.hope.hotel.mapper.HotelMapper;
import com.hope.hotel.mapper.LocationMapper;
import com.hope.hotel.mapper.PolicyMapper;
import com.hope.hotel.mapper.RoomsMapper;
import com.hope.hotel.service.HotelService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import static com.hope.hotel.common.Result.success;


/**
 * @作者 TD
 * @日期 2025/5/18
 */

@Service
@RequiredArgsConstructor
public class HotelServiceImpl extends ServiceImpl<HotelMapper, Hotel> implements HotelService  {

    private final HotelMapper hotelMapper;
    private final LocationMapper locationMapper;
    private final PolicyMapper policyMapper;
    private final AmenitiesMapper amenitiesMapper;
    private final RoomsMapper roomsMapper;

    // TODO 实现后台管理
    @Override
    public Result getAdminHotelInfo(String adminId) {
        LambdaQueryWrapper<Hotel> qw = new LambdaQueryWrapper<>();
        qw.eq(Hotel::getAdminId, adminId);
        // 只查找一个
        qw.last("limit 1");
        Hotel hotel = hotelMapper.selectOne(qw);
        if (hotel == null) {
            return Result.error("没有找到该酒店");
        }
        HotelNewDAO hotelNewDAO = BeanUtil.copyProperties(hotel, HotelNewDAO.class);
        hotelNewDAO.setId(String.valueOf(hotel.getHotelId()));
        hotelNewDAO.setLogo(hotel.getAvatar());
        hotelNewDAO.setDesc(hotel.getDescription());
        return success(hotelNewDAO);
    }

    @Override
    public Result createHotel(HotelNewDAO hotelNewDAO, String adminId) {
        // TODO: 2025/5/29  创建酒店
        Hotel hotel = BeanUtil.copyProperties(hotelNewDAO, Hotel.class);
        hotel.setCreatedAt(LocalDateTime.now());
        hotel.setAvatar(hotelNewDAO.getLogo());
        System.out.println("adminId = " + adminId);
        System.out.println("hotel = " + hotel);
        hotel.setAdminId(Long.valueOf(adminId));
        hotel.setDescription(hotelNewDAO.getDesc());

        boolean save = this.save(hotel);
        if (! save ) {
            return Result.error("创建失败");
        }
        return success("创建成功");
    }

    @Override
    public Result updateHotel(HotelNewDAO hotelNewDAO, String adminId) {
        // 更新酒店信息
        Hotel hotel = BeanUtil.copyProperties(hotelNewDAO, Hotel.class);
        hotel.setAvatar(hotelNewDAO.getLogo());
        UpdateWrapper<Hotel> uw = new UpdateWrapper<>();
        uw.eq("admin_id", adminId);

        boolean update = update(hotel, uw);
        return update ? success("更新成功") : Result.error("更新失败");
    }

    @Override
    public Result getHotelList(int page, int pageSize) {
        // 1. 创建分页对象
        Page<Hotel> hotelPage = new Page<>(page, pageSize);

        // 2. 创建查询条件（这里可以根据需要添加查询条件）
        QueryWrapper<Hotel> queryWrapper = new QueryWrapper<>();
        // 示例：只查询状态为1的酒店
        // queryWrapper.eq("status", 1);

        // 3. 执行分页查询
        Page<Hotel> resultPage = baseMapper.selectPage(hotelPage, queryWrapper);
        String total = String.valueOf(resultPage.getTotal());
        // 4. 获取查询结果
        List<Hotel> hotelList = resultPage.getRecords();
        // 5. 返回结果
        List<HotelVO> hotelVOList = new LinkedList<>();

        hotelList.forEach(h->{
            HotelVO hotelVO = BeanUtil.copyProperties(h, HotelVO.class);
            hotelVO.setHotelId(String.valueOf(h.getHotelId()));
            hotelVOList.add(hotelVO);
        });
        return success(hotelVOList, total);
    }

    @Override
    public Result getHotelLocation(String hotelId) {
        // 根据酒店ID查询位置信息
        LambdaQueryWrapper<Location> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Location::getHotelId, hotelId);
        Location location = locationMapper.selectOne(queryWrapper);
        
        if (location == null) {
            return Result.error("未找到该酒店的位置信息");
        }
        
        // 将PO转换为DTO
        LocationDTO locationDTO = new LocationDTO();
        BeanUtils.copyProperties(location, locationDTO);
        
        // 这里需要处理transportation和attractions的转换，实际实现可能需要根据数据库设计调整
        // 假设location对象已经包含了这些信息
        
        return Result.success(locationDTO);
    }

    @Override
    @Transactional
    public Result createHotelLocation(LocationDTO locationDTO, String adminId) {
        // 检查酒店是否存在
        Hotel hotel = getById(locationDTO.getHotelId());
        if (hotel == null) {
            return Result.error("酒店不存在");
        }
        
        // 检查是否已存在位置信息
        LambdaQueryWrapper<Location> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Location::getHotelId, locationDTO.getHotelId());
        if (locationMapper.selectCount(queryWrapper) > 0) {
            return Result.error("该酒店已有位置信息，请使用更新接口");
        }
        
        // 创建位置信息
        Location location = new Location();
        BeanUtils.copyProperties(locationDTO, location);
        location.setId(UUID.randomUUID().toString());
        
        // 这里需要处理transportation和attractions的转换，实际实现可能需要根据数据库设计调整
        // 假设Location实体类能够存储这些信息
        
        locationMapper.insert(location);
        
        // 返回创建后的数据
        locationDTO.setId(location.getId());
        return Result.success(locationDTO);
    }

    @Override
    @Transactional
    public Result updateHotelLocation(LocationDTO locationDTO, String adminId) {
        // 检查酒店是否存在
        Hotel hotel = getById(locationDTO.getHotelId());
        if (hotel == null) {
            return Result.error("酒店不存在");
        }
        
        // 检查位置信息是否存在
        Location existingLocation = null;
        if (locationDTO.getId() != null) {
            existingLocation = locationMapper.selectById(locationDTO.getId());
        }
        
        if (existingLocation == null) {
            // 如果没有找到指定ID的位置信息，尝试通过酒店ID查找
            LambdaQueryWrapper<Location> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Location::getHotelId, locationDTO.getHotelId());
            existingLocation = locationMapper.selectOne(queryWrapper);
            
            if (existingLocation == null) {
                return Result.error("未找到该酒店的位置信息，请先创建");
            }
            
            // 设置ID以便更新
            locationDTO.setId(existingLocation.getId());
        }
        
        // 更新位置信息
        Location location = new Location();
        BeanUtils.copyProperties(locationDTO, location);
        
        // 这里需要处理transportation和attractions的转换，实际实现可能需要根据数据库设计调整
        
        locationMapper.updateById(location);
        
        return Result.success(locationDTO);
    }

    @Override
    public Result getHotelPolicy(String hotelId) {
        // 根据酒店ID查询政策信息
        LambdaQueryWrapper<Policy> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Policy::getHotelId, hotelId);
        Policy policy = policyMapper.selectOne(queryWrapper);
        
        if (policy == null) {
            return Result.error("未找到该酒店的政策信息");
        }
        
        // 将PO转换为DTO
        PolicyDTO policyDTO = new PolicyDTO();
        BeanUtils.copyProperties(policy, policyDTO);
        
        // 处理特殊字段，如支付方式列表等
        // 假设policy对象已经包含了这些信息
        
        return Result.success(policyDTO);
    }

    @Override
    @Transactional
    public Result createHotelPolicy(PolicyDTO policyDTO, String adminId) {
        // 检查酒店是否存在
        Hotel hotel = getById(policyDTO.getHotelId());
        if (hotel == null) {
            return Result.error("酒店不存在");
        }
        
        // 检查是否已存在政策信息
        LambdaQueryWrapper<Policy> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Policy::getHotelId, policyDTO.getHotelId());
        if (policyMapper.selectCount(queryWrapper) > 0) {
            return Result.error("该酒店已有政策信息，请使用更新接口");
        }
        
        // 创建政策信息
        Policy policy = new Policy();
        BeanUtils.copyProperties(policyDTO, policy);
        policy.setId(UUID.randomUUID().toString());
        
        // 处理特殊字段，如支付方式列表等
        // 假设Policy实体类能够存储这些信息
        
        policyMapper.insert(policy);
        
        // 返回创建后的数据
        policyDTO.setId(policy.getId());
        return Result.success(policyDTO);
    }

    @Override
    @Transactional
    public Result updateHotelPolicy(PolicyDTO policyDTO, String adminId) {
        // 检查酒店是否存在
        Hotel hotel = getById(policyDTO.getHotelId());
        if (hotel == null) {
            return Result.error("酒店不存在");
        }
        
        // 检查政策信息是否存在
        Policy existingPolicy = null;
        if (policyDTO.getId() != null) {
            existingPolicy = policyMapper.selectById(policyDTO.getId());
        }
        
        if (existingPolicy == null) {
            // 如果没有找到指定ID的政策信息，尝试通过酒店ID查找
            LambdaQueryWrapper<Policy> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Policy::getHotelId, policyDTO.getHotelId());
            existingPolicy = policyMapper.selectOne(queryWrapper);
            
            if (existingPolicy == null) {
                return Result.error("未找到该酒店的政策信息，请先创建");
            }
            
            // 设置ID以便更新
            policyDTO.setId(existingPolicy.getId());
        }
        
        // 更新政策信息
        Policy policy = new Policy();
        BeanUtils.copyProperties(policyDTO, policy);
        
        // 处理特殊字段，如支付方式列表等
        
        policyMapper.updateById(policy);
        
        return Result.success(policyDTO);
    }

    @Override
    public Result getHotelAmenities(String hotelId) {
        // 根据酒店ID查询设施信息
        LambdaQueryWrapper<Amenities> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Amenities::getHotelId, hotelId);
        Amenities amenities = amenitiesMapper.selectOne(queryWrapper);
        
        if (amenities == null) {
            return Result.error("未找到该酒店的设施信息");
        }
        
        // 将PO转换为DTO
        AmenitiesDTO amenitiesDTO = new AmenitiesDTO();
        BeanUtils.copyProperties(amenities, amenitiesDTO);
        
        // 处理categories列表等
        // 假设amenities对象已经包含了这些信息
        
        return Result.success(amenitiesDTO);
    }

    @Override
    @Transactional
    public Result createHotelAmenities(AmenitiesDTO amenitiesDTO, String adminId) {
        // 检查酒店是否存在
        Hotel hotel = getById(amenitiesDTO.getHotelId());
        if (hotel == null) {
            return Result.error("酒店不存在");
        }
        
        // 检查是否已存在设施信息
        LambdaQueryWrapper<Amenities> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Amenities::getHotelId, amenitiesDTO.getHotelId());
        if (amenitiesMapper.selectCount(queryWrapper) > 0) {
            return Result.error("该酒店已有设施信息，请使用更新接口");
        }
        
        // 创建设施信息
        Amenities amenities = new Amenities();
        BeanUtils.copyProperties(amenitiesDTO, amenities);
        amenities.setId(UUID.randomUUID().toString());
        
        // 处理categories列表等
        // 假设Amenities实体类能够存储这些信息
        
        amenitiesMapper.insert(amenities);
        
        // 返回创建后的数据
        amenitiesDTO.setId(amenities.getId());
        return Result.success(amenitiesDTO);
    }

    @Override
    @Transactional
    public Result updateHotelAmenities(AmenitiesDTO amenitiesDTO, String adminId) {
        // 检查酒店是否存在
        Hotel hotel = getById(amenitiesDTO.getHotelId());
        if (hotel == null) {
            return Result.error("酒店不存在");
        }
        
        // 检查设施信息是否存在
        Amenities existingAmenities = null;
        if (amenitiesDTO.getId() != null) {
            existingAmenities = amenitiesMapper.selectById(amenitiesDTO.getId());
        }
        
        if (existingAmenities == null) {
            // 如果没有找到指定ID的设施信息，尝试通过酒店ID查找
            LambdaQueryWrapper<Amenities> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Amenities::getHotelId, amenitiesDTO.getHotelId());
            existingAmenities = amenitiesMapper.selectOne(queryWrapper);
            
            if (existingAmenities == null) {
                return Result.error("未找到该酒店的设施信息，请先创建");
            }
            
            // 设置ID以便更新
            amenitiesDTO.setId(existingAmenities.getId());
        }
        
        // 更新设施信息
        Amenities amenities = new Amenities();
        BeanUtils.copyProperties(amenitiesDTO, amenities);
        
        // 处理categories列表等
        
        amenitiesMapper.updateById(amenities);
        
        return Result.success(amenitiesDTO);
    }

    @Override
    public Result getHotelDetail(String hotelId) {
        // 1. 获取酒店基本信息
        Hotel hotel = getById(hotelId);
        if (hotel == null) {
            return Result.error("未找到该酒店");
        }
        
        // 创建返回结果Map
        Map<String, Object> resultMap = new HashMap<>();
        
        // 2. 处理基本信息
        Map<String, Object> basicInfo = new HashMap<>();
        basicInfo.put("id", hotel.getHotelId());
        basicInfo.put("name", hotel.getName());
        basicInfo.put("address", hotel.getAddress());
        basicInfo.put("city", hotel.getCity());
        basicInfo.put("rating", hotel.getRating());
        basicInfo.put("description", hotel.getDescription());
        basicInfo.put("phone", hotel.getPhone());
        basicInfo.put("avatar", hotel.getAvatar());
        basicInfo.put("createdAt", hotel.getCreatedAt());
        
        resultMap.put("basic", basicInfo);
        
        // 3. 获取房间信息
        LambdaQueryWrapper<Rooms> roomsQueryWrapper = new LambdaQueryWrapper<>();
        roomsQueryWrapper.eq(Rooms::getHotelId, hotelId);
        List<Rooms> roomsList = roomsMapper.selectList(roomsQueryWrapper);
        
        List<Map<String, Object>> roomsData = new LinkedList<>();
        for (Rooms room : roomsList) {
            Map<String, Object> roomMap = new HashMap<>();
            roomMap.put("id", room.getId());
            roomMap.put("name", room.getName());
            roomMap.put("capacity", room.getCapacity());
            roomMap.put("size", room.getSize());
            roomMap.put("price", room.getPrice());
            roomMap.put("bedType", room.getBedType());
            roomMap.put("imageUrl", room.getImageUrl());
            roomMap.put("galleryUrls", room.getGalleryUrls());
            roomMap.put("tags", room.getTags());
            roomMap.put("amenities", room.getAmenities());
            roomMap.put("description", room.getDescription());
            
            roomsData.add(roomMap);
        }
        
        resultMap.put("rooms", roomsData);
        
        // 4. 获取酒店设施信息
        LambdaQueryWrapper<Amenities> amenitiesQueryWrapper = new LambdaQueryWrapper<>();
        amenitiesQueryWrapper.eq(Amenities::getHotelId, hotelId);
        Amenities amenities = amenitiesMapper.selectOne(amenitiesQueryWrapper);
        
        if (amenities != null) {
            Map<String, Object> amenitiesMap = new HashMap<>();
            amenitiesMap.put("id", amenities.getId());
            amenitiesMap.put("categories", amenities.getCategories());
            
            resultMap.put("amenities", amenitiesMap);
        }
        
        // 5. 获取酒店位置信息
        LambdaQueryWrapper<Location> locationQueryWrapper = new LambdaQueryWrapper<>();
        locationQueryWrapper.eq(Location::getHotelId, hotelId);
        Location location = locationMapper.selectOne(locationQueryWrapper);
        
        if (location != null) {
            Map<String, Object> locationMap = new HashMap<>();
            locationMap.put("id", location.getId());
            locationMap.put("latitude", location.getLatitude());
            locationMap.put("longitude", location.getLongitude());
            locationMap.put("address", location.getAddress());
            locationMap.put("city", location.getCity());
            locationMap.put("country", location.getCountry());
            locationMap.put("postalCode", location.getPostalCode());
            locationMap.put("province", location.getProvince());
            locationMap.put("transportation", location.getTransportation());
            locationMap.put("attractions", location.getAttractions());
            
            resultMap.put("location", locationMap);
        }
        
        // 6. 获取酒店政策信息
        LambdaQueryWrapper<Policy> policyQueryWrapper = new LambdaQueryWrapper<>();
        policyQueryWrapper.eq(Policy::getHotelId, hotelId);
        Policy policy = policyMapper.selectOne(policyQueryWrapper);
        
        if (policy != null) {
            Map<String, Object> policyMap = new HashMap<>();
            policyMap.put("id", policy.getId());
            policyMap.put("checkInTime", policy.getCheckInTime());
            policyMap.put("checkOutTime", policy.getCheckOutTime());
            policyMap.put("minAdvanceReservation", policy.getMinAdvanceReservation());
            policyMap.put("maxAdvanceReservation", policy.getMaxAdvanceReservation());
            policyMap.put("freeCancellationHours", policy.getFreeCancellationHours());
            policyMap.put("cancellationFeePercent", policy.getCancellationFeePercent());
            policyMap.put("paymentMethods", policy.getPaymentMethods());
            policyMap.put("prepaymentRequired", policy.getPrepaymentRequired());
            policyMap.put("prepaymentPercent", policy.getPrepaymentPercent());
            policyMap.put("petsAllowed", policy.getPetsAllowed());
            policyMap.put("petFee", policy.getPetFee());
            policyMap.put("childrenAllowed", policy.getChildrenAllowed());
            policyMap.put("childAgeThreshold", policy.getChildAgeThreshold());
            policyMap.put("extraBedAllowed", policy.getExtraBedAllowed());
            policyMap.put("extraBedFee", policy.getExtraBedFee());
            
            resultMap.put("policy", policyMap);
        }
        
        return Result.success(resultMap);
    }

    @Override
    public Result searchHotels(String destination, String checkIn, String checkOut, Integer guests, int page, int pageSize) {
        // 创建分页对象
        Page<Hotel> hotelPage = new Page<>(page, pageSize);
        
        // 创建查询条件
        QueryWrapper<Hotel> queryWrapper = new QueryWrapper<>();
        
        // 根据目的地(城市或酒店名称)筛选
        if (destination != null && !destination.trim().isEmpty()) {
            queryWrapper.and(wrapper -> wrapper
                .like("city", destination)
                .or()
                .like("name", destination)
                .or()
                .like("address", destination)
            );
        }
        
        // 执行分页查询
        Page<Hotel> resultPage = baseMapper.selectPage(hotelPage, queryWrapper);
        String total = String.valueOf(resultPage.getTotal());
        
        // 获取查询结果
        List<Hotel> hotelList = resultPage.getRecords();
        
        // 过滤满足入住人数要求的酒店
        // 注意：这里需要根据实际的数据结构来调整筛选逻辑
        // 这里假设通过查询房间来进行人数筛选
        if (guests != null && guests > 1) {
            // 可以通过查询房间信息进行过滤
            // 实际实现可能需要联表查询或者多次查询
            hotelList = hotelList.stream()
                .filter(hotel -> {
                    // 查询该酒店是否有满足人数要求的房间
                    LambdaQueryWrapper<Rooms> roomsQuery = new LambdaQueryWrapper<>();
                    roomsQuery.eq(Rooms::getHotelId, hotel.getHotelId())
                            .ge(Rooms::getCapacity, guests);
                    return roomsMapper.selectCount(roomsQuery) > 0;
                })
                .toList();
        }
        
        // 转换为VO对象返回
        List<HotelVO> hotelVOList = new LinkedList<>();
        hotelList.forEach(h -> {
            HotelVO hotelVO = BeanUtil.copyProperties(h, HotelVO.class);
            hotelVO.setHotelId(String.valueOf(h.getHotelId()));
            hotelVOList.add(hotelVO);
        });
        
        return success(hotelVOList,total );
    }
}
